local skynet = require "skynet"
local filename = "slotmgr.lua"
local filelog = require "filelog"
local queue = require "skynet.queue"
local base = require "base"
local redisdao = require "redisdao"
local tabletool = require "tabletool"
local json = require "cjson"
json.encode_sparse_array(true,1,1)

local SlotTool = require "slottool"
require "lpenum"

------------
--枚举类

--系统输钱上限基值,默认100万
local SystemLoseLimit_Base = 1000000

--系统输钱上限控制系数
local SystemLoseLimit_Factor = 0.08

--开奖类型
local LotteryType = {
    LOTTERY_TYPE_SYSTEM_WIN = 1,   --系统必赢
    LOTTERY_TYPE_SYSTEM_LOSE = 2,  --系统必输
    LOTTERY_TYPE_NORMAL = 3,       --正常开奖
}

----------------------
--数据表，可以改变

--倍率列表
--key为：图标id = 图标类型 + 图标subid
--[1101] = 2 表示：飞禽倍率为2
--
local Odds_type = {
    -- 单个数字（Straight Bet）：投注于一个数字的格上，赔率1:35
    -- 37个(下注区域编号: 0 ~~ 36) type_1
    [1] = {0, 36, 35},   -- {范围s, 范围e, 倍率}

    -- 两个数字组合（Split Bet）：投注于两个数字之间的线上，赔率1:17
    -- 60个(下注区域编号: 37 ~~ 96) type_2
    [2] = {37, 96, 17},

    -- 三个数字组合（Street Bet）：投注于横行三个数字与外围投注区的线上，赔率1:11
    -- 14个(下注区域编号: 97 ~~ 110) type_3
    [3] = {97, 110, 11},

    -- 四个数字组合（Corner Bet）：投注于四个数字交接之间的点上，赔率1:8
    -- 23个(下注区域编号: 111 ~~ 133) type_4
    [4] = {111, 133, 8},

    -- 六个数字组合（Sixline Bet或Alley Bet）：投注于两行横行数字与外围投注区的交接点上，赔率1:5
    -- 11个(下注区域编号: 134 ~~ 144) type_5
    [5] = {134, 144, 5},

    -- 颜色：可投注开出红或黑色号码，赔率1:1
    -- 2个(下注区域编号: 145 ~~ 146) type_6   :红 黑
    [6] = {145, 146, 1},

    -- 单双：可投注开出单或双数号码，赔率1:1
    -- 2个(下注区域编号: 147 ~~ 148) type_7   :双 单
    [7] = {147, 148, 1},

    -- 大小：1-18、19-36：可投注开出号码属上半（小）或下半段（大），赔率1:1
    -- 2个(下注区域编号: 149 ~~ 150) type_8   :小 大
    [8] = {149, 150, 1},

    -- 12个数字组合（Dozen Bet）：可投注开出号码属于前、中或后12个号码，赔率1:2
    -- 3个(下注区域编号: 151 ~~ 153) type_9   :前(1~12) 中(13~24) 后(25~36)
    [9] = {151, 153, 2},
    
    -- 直行（Column Bet）：可投注开出号码属于第一、二或三直行，赔率1:2
    -- 3个(下注区域编号: 154 ~~ 156) type_10  :第一行 第二行 第三行
    [10] = {154, 156, 2},
}

-- 数字关联下注区域
local association_with_num = {
    [0] = {37,49,61,97,98,133},

    [1] = {
        37,38,73,97,99,                 -- 2 3
        111,                            -- 4
        133,134,145,148,149,151,154     -- others
    },
    [2] = {
        49,50,73,85,97,98,99,
        111,122,
        133,134,146,147,149,151,155
    },
    [3] = {
        61,62,85,98,99,
        122,
        133,134,145,148,149,151,156
    },
    [4] = {
        38,39,74,100,
        111,112,
        134,135,146,147,149,151,154
    },
    [5] = {
        50,51,74,86,100,
        111,112,122,123,
        134,135,145,148,149,151,155
    },
    [6] = {
        62,63,86,100,
        122,123,
        134,135,146,147,149,151,156
    },
    [7] = {
        39,40,75,101,
        112,113,
        135,136,145,148,149,151,154
    },
    [8] = {
        51,52,75,87,101,
        112,113,123,124,
        135,136,146,147,149,151,155
    },
    [9] = {
        63,64,87,101,
        123,124,
        135,136,145,148,149,151,156
    },
    [10] = {
        40,41,76,102,
        113,114,
        136,137,146,147,149,151,154
    },
    [11] = {
        52,53,76,88,102,
        113,114,124,125,
        136,137,146,148,149,151,155
    },
    [12] = {
        64,65,88,102,
        124,125,
        136,137,145,147,149,151,156
    },

    [13] = {
        41,42,77,103,
        114,115,
        137,138,146,148,149,152,154
    },
    [14] = {
        53,54,77,89,103,
        114,115,125,126,
        137,138,145,147,149,152,155
    },
    [15] = {
        65,66,89,103,
        125,126,
        137,138,146,148,149,152,156
    },
    [16] = {
        42,43,78,104,
        115,116,
        138,139,145,147,149,152,154
    },
    [17] = {
        54,55,78,90,104,
        115,116,126,127,
        138,139,146,148,149,152,155
    },
    [18] = {
        66,67,90,104,
        126,127,
        138,139,145,147,149,152,156
    },
    [19] = {
        43,44,79,105,
        116,117,
        139,140,145,148,150,152,154
    },
    [20] = {
        55,56,79,91,105,
        116,117,127,128,
        139,140,146,147,150,152,155
    },
    [21] = {
        67,68,91,105,
        127,128,
        139,140,145,148,150,152,156
    },
    [22] = {
        44,45,80,106,
        117,118,
        140,141,146,147,150,152,154
    },
    [23] = {
        56,57,80,92,106,
        117,118,128,129,
        140,141,145,148,150,152,155
    },
    [24] = {
        68,69,92,106,
        128,129,
        140,141,146,147,150,152,156
    },

    [25] = {
        45,46,81,107,
        118,119,
        141,142,145,148,150,153,154
    },
    [26] = {
        57,58,81,93,107,
        118,119,129,130,
        141,142,146,147,150,153,155
    },
    [27] = {
        69,70,93,107,
        129,130,
        141,142,145,148,150,153,156
    },
    [28] = {
        46,47,82,108,
        119,120,
        142,143,146,147,150,153,154
    },
    [29] = {
        58,59,82,94,108,
        119,120,130,131,
        142,143,146,148,150,153,155
    },
    [30] = {
        70,71,94,108,
        130,131,
        142,143,145,147,150,153,156
    },
    [31] = {
        47,48,83,109,
        120,121,
        143,144,146,148,150,153,154
    },
    [32] = {
        59,60,83,95,109,
        120,121,131,132,
        143,144,145,147,150,153,155
    },
    [33] = {
        71,72,95,109,
        131,132,
        143,144,146,148,150,153,156
    },
    [34] = {
        48,84,110,
        121,
        144,145,147,150,153,154
    },
    [35] = {
        60,84,96,110,
        121,132,
        144,146,148,150,153,155
    },
    [36] = {
        72,96,110,
        132,
        144,145,147,150,153,156
    },
}

--图标权重列表
local Weight_list = {
    [0] = 100,  --0
    [1] = 100,   --1
    [2] = 100,  --2
    [3] = 100,   --3
    [4] = 100,  --4
    [5] = 100,   --5
    [6] = 100,  --6
    [7] = 100,   --7
    [8] = 100,   --8
    [9] = 100,   --9
    [10] = 100,   --10
    [11] = 100,   --11
    [12] = 100,   --12
    [13] = 100,   --13
    [14] = 100,    --14
    [15] = 100,    --15
    [16] = 100,   --16
    [17] = 100,   --17
    [18] = 100,   --18
    [19] = 100,   --19
    [20] = 100,   --20
    [21] = 100,   --21
    [22] = 100,   --22
    [23] = 100,   --23
    [24] = 100,   --24
    [25] = 100,   --25
    [26] = 100,   --26
    [27] = 100,   --27
    [28] = 100,   --28
    [29] = 100,   --29
    [30] = 100,   --30
    [31] = 100,   --31
    [32] = 100,   --32
    [33] = 100,   --33
    [34] = 100,   --34
    [35] = 100,   --35
    [36] = 100,   --36
}

--系统库存概率表
--S = 库存值
local S_list = {
    [1] = { -- S < -500万
        nohit = 1.00,   --必不中概率
        normal = 0.00,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [2] = { -- -500万<=S<-100万
        nohit = 0.80,   --必不中概率
        normal = 0.20,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [3] = { -- -100万<=S<-20万
        nohit = 0.60,   --必不中概率
        normal = 0.40,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [4] = { -- -20万<=S<-10万
        nohit = 0.30,   --必不中概率
        normal = 0.70,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [5] = { -- -10万<=S<200万
        nohit = 0.00,   --必不中概率
        normal = 1.00,  --正常开奖概率
        hit = 0.00,     --必中概率
    },
    [6] = { -- 200万<=S<1000万
        nohit = 0.00,   --必不中概率
        normal = 0.80,  --正常开奖概率
        hit = 0.20,     --必中概率
    },
    [7] = { -- 1000万<=S<5000万
        nohit = 0.00,   --必不中概率
        normal = 0.60,  --正常开奖概率
        hit = 0.40,     --必中概率
    },
    [8] = { -- 5000万<=S<1亿
        nohit = 0.00,   --必不中概率
        normal = 0.50,  --正常开奖概率
        hit = 0.50,     --必中概率
    },
    [9] = { -- S>=1亿
        nohit = 0.00,   --必不中概率
        normal = 0.40,  --正常开奖概率
        hit = 0.60,     --必中概率
    },
}

local function get_odd_by_result(result_id)
    if not result_id or result_id < 0 or result_id > 156 then return 0 end
    for _, v in ipairs(Odds_type) do
        if result_id >= v[1] and result_id <= v[2] then
            return v[3] + 1     -- +1 基础倍率
        end
    end
    return 0
end

--------------------------
--辅助表

--图标概率表，由权重表生成
local Prob_list = nil

--图标总权值,，由权重表生成
local Total_weight = nil

-------------------------------
-------------------------------
---工具类

--
--获得系统输钱上限
--
function SlotTool.get_system_lose_limit(gamename)
    local loselimit = 0
    local S = SlotTool.get_static_inventory_from_redis(gamename)
    if S < 0 then
        loselimit = SystemLoseLimit_Base
    else
        loselimit = math.floor(S * SystemLoseLimit_Factor) + SystemLoseLimit_Base
    end

    return loselimit
end

--
--获得返钱数
--
function SlotTool.get_rtm(id, total_bet_list)
    local bet_id = id % 1000
    local odds = get_odd_by_result(bet_id)
    local rtm = odds * (total_bet_list[bet_id] or 0)
    local associations = association_with_num[bet_id]
    for _, v in ipairs(associations) do
        rtm = rtm + get_odd_by_result(v) * (total_bet_list[v] or 0)
    end
    return rtm
end

--
--检测亏损值是否超过输钱上限
--
function SlotTool.check_is_greater_loselimit(id, total_bet, total_bet_list, is_robot_banker, loselimit)
    local rtm = SlotTool.get_rtm(id,total_bet_list)
    local ksz = total_bet - rtm
    if (is_robot_banker and ksz < -loselimit)
    or (not is_robot_banker and ksz > loselimit) then
        return true
    end

    return false
end

--更新图标概率表
function SlotTool.update_picture_prob_list()
    ----------------- for test -----------------
    if LPTestWeightConfig and LPTestWeightConfig.use then
        Weight_list = LPTestWeightConfig[LPTestWeightConfig.use]
    end


    local prob_list = {}

    local total_prob = 0
    local total_weight = SlotTool.calculate_total_weight(Weight_list)
    for id,w in pairs(Weight_list) do
        prob_list[id] = w / total_weight
        total_prob = total_prob + prob_list[id]
    end
    --总概率应为1
    if math.ceil(total_prob * 100) ~= 100 then
        filelog.sys_error("total probability not equal to 1!",total_prob,math.ceil(total_prob * 100))
    end

    return prob_list,total_weight
end

--
--获取开奖类型
--返回 LotteryType类型
--
function SlotTool.get_lottery_type(gamename)
    --获取库存值
    local inventory = SlotTool.get_static_inventory_from_redis(gamename)

    local item = nil
    local s = inventory
    local a = 10000
    if s < -500 * a then
        item = S_list[1]
    elseif s >= -500 * a and s < -100 * a then
        item = S_list[2]
    elseif s >= -100 * a and s < -20 * a  then
        item = S_list[3]
    elseif s >= -20 * a and s < -10 * a then
        item = S_list[4]
    elseif s >= -10 * a and s < 200 * a then
        item = S_list[5]
    elseif s >= 200 * a and s < 1000 * a then
        item = S_list[6]
    elseif s >= 1000 * a and s < 5000 * a then
        item = S_list[7]
    elseif s >= 5000 * a and s < 10000 * a then
        item = S_list[8]
    elseif s >= 10000 * a then
        item = S_list[9]
    end

     --根据概率获取随机开奖类型
    local r = base.get_random(1, 1000)
    local hit = math.floor(item.hit * 1000)
    local nohit = hit + math.floor(item.nohit * 1000)
    local normal = nohit + math.floor(item.normal * 1000) 
    if r <= hit then
        return LotteryType.LOTTERY_TYPE_SYSTEM_LOSE
    elseif r <= nohit then
        return LotteryType.LOTTERY_TYPE_SYSTEM_WIN
    elseif r <= normal then
        return LotteryType.LOTTERY_TYPE_NORMAL
    end
end

--
--获取系统输赢列表
--
function SlotTool.get_system_win_lose_list(total_bet_list, total_bet, is_robot_banker)
    local sys_win_list = {}
    local sys_lose_list = {}

    if is_robot_banker then
        for id, w in pairs(Weight_list) do
            local odds = get_odd_by_result(id)
            local bet_id = id
            if w > 0 and odds > 0 and total_bet_list[bet_id] then
                local rtm = odds * total_bet_list[bet_id]   --返钱数
                local associations = association_with_num[bet_id]
                for _, v in ipairs(associations) do
                    rtm = rtm + get_odd_by_result(v) * (total_bet_list[v] or 0)
                end
                if rtm < total_bet then
                    table.insert(sys_win_list,id)
                elseif rtm > total_bet then
                    table.insert(sys_lose_list,id)
                end
            end
        end
    else
        for id, w in pairs(Weight_list) do
            local odds = get_odd_by_result(id)
            local bet_id = id
            if w > 0 and odds > 0 and total_bet_list[bet_id] then
                local rtm = odds * total_bet_list[bet_id]   --返钱数
                local associations = association_with_num[bet_id]
                for _, v in ipairs(associations) do
                    rtm = rtm + get_odd_by_result(v) * (total_bet_list[v] or 0)
                end
                if rtm > total_bet then
                    table.insert(sys_win_list,id)
                elseif rtm < total_bet then
                    table.insert(sys_lose_list,id)
                end
            end
        end
    end
    
    return sys_win_list,sys_lose_list
end

--
--获取系统必输随机结果
--
function SlotTool.get_mustlose_random_result(sys_lose_list, total_bet_list, gamename, total_bet, is_robot_banker)
    local loselimit = SlotTool.get_system_lose_limit(gamename)

    if sys_lose_list and #sys_lose_list > 0 then
        local lose_w_list = {}
        local total_weight = 0
        for _,id in pairs(sys_lose_list) do
            local is_ok = SlotTool.check_is_greater_loselimit(id,total_bet,total_bet_list,is_robot_banker,loselimit)
            if not is_ok then
                lose_w_list[id] = Weight_list[id]
                total_weight = total_weight + lose_w_list[id]
            end
        end

        if next(lose_w_list) ~= nil then
            return SlotTool.get_random_result_by_weightlist(lose_w_list,total_weight)
        else
            return SlotTool.get_min_spin_result(total_bet_list,is_robot_banker)
        end
    end

    --当前押注使系统必定赢，则选择玩家赢钱最多的结果
    return SlotTool.get_max_spin_result(total_bet_list,is_robot_banker)
end

--
--获取系统必赢随机结果
--
function SlotTool.get_mustwin_random_result(sys_win_list, total_bet_list, is_robot_banker)
   if sys_win_list and #sys_win_list > 0 then
        local win_w_list = {}
        local total_weight = 0
        for _,id in pairs(sys_win_list) do
            win_w_list[id] = Weight_list[id]
            total_weight = total_weight + win_w_list[id]
        end
        
        local id = SlotTool.get_random_result_by_weightlist(win_w_list,total_weight)
        return id
    end

    --当前押注使系统必输，则选择玩家赢钱最少的结果
    return SlotTool.get_min_spin_result(total_bet_list,is_robot_banker)
end

--
--获取普通随机结果
--
function SlotTool.get_normal_random_result(sys_lose_list, total_bet_list, gamename, total_bet, is_robot_banker)
    Total_weight = Total_weight or SlotTool.calculate_total_weight(Weight_list)

    --产生随机结果
    if not sys_lose_list then
        return SlotTool.get_random_result_by_weightlist(Weight_list,Total_weight)
    end
    
    local random_id_list = tabletool.deepcopy(Weight_list)
    local loselimit = SlotTool.get_system_lose_limit(gamename)

    --去除超上限亏损
    if sys_lose_list and #sys_lose_list > 0 then
        for _,id in pairs(sys_lose_list) do
            local is_ok = SlotTool.check_is_greater_loselimit(id,total_bet,total_bet_list,is_robot_banker,loselimit)
            if is_ok then
                random_id_list[id] = nil
            end
        end
    end

    --所有项超上限，则返回最小的
    if next(random_id_list) == nil then
        return SlotTool.get_min_spin_result(total_bet_list,is_robot_banker)
    end

    return SlotTool.get_random_result_by_weightlist(random_id_list)
end

--
--产生一个随机旋转结果
--
function SlotTool.gen_random_spin_result(gamename, total_bet_list, total_bet, avg_bet, is_robot_banker, is_random)
    local result_id = nil
    local result_list = {}

    --随机开奖
    --------------- for test ---------------
    if LPTestWeightConfig and LPTestWeightConfig.use then
        is_random = true
    end


    if is_random then
        result_id = SlotTool.get_normal_random_result()
    else
        --计算系统输赢列表
        local sys_win_list,sys_lose_list = SlotTool.get_system_win_lose_list(total_bet_list,total_bet,is_robot_banker)

        --获取开奖类型,分：系统必输，系统必赢，随机开奖3种
        local lottery_type = SlotTool.get_lottery_type(gamename)
        if lottery_type == LotteryType.LOTTERY_TYPE_SYSTEM_LOSE then     --系统必输
            result_id = SlotTool.get_mustlose_random_result(sys_lose_list,total_bet_list,gamename,total_bet,is_robot_banker)
        elseif lottery_type == LotteryType.LOTTERY_TYPE_SYSTEM_WIN then  --系统必赢
            result_id = SlotTool.get_mustwin_random_result(sys_win_list,total_bet_list,is_robot_banker)
        else    --随机开奖
            result_id = SlotTool.get_normal_random_result(sys_lose_list,total_bet_list,gamename,total_bet,is_robot_banker)
        end
    end
    table.insert(result_list,result_id)
    
    return result_list
end

--
--获取最小奖励
--
function SlotTool.get_min_spin_result(total_bet_list, is_robot_banker)
    local min_id = 0
    local min_rtm = 100000000000
    if not is_robot_banker then
        min_rtm = 0
    end
    
    --循环每一种情况,求返钱数最小的
    for id,w in pairs(Weight_list) do
        local odds = get_odd_by_result(id)
        local bet_id = id % 1000
        if w > 0 and odds > 0 and total_bet_list[bet_id] then
            local rtm = odds * total_bet_list[bet_id]   --返钱数
            local associations = association_with_num[bet_id]
            for _, v in ipairs(associations) do
                rtm = rtm + get_odd_by_result(v) * (total_bet_list[v] or 0)
            end
            if is_robot_banker then
                if min_rtm > rtm then
                    min_rtm = rtm
                    min_id = id
                end
            else
                if min_rtm < rtm then
                    min_rtm = rtm
                    min_id = id
                end
            end
        end
    end
    
    return min_id
end

--
--获取最大奖励
--
function SlotTool.get_max_spin_result(total_bet_list, is_robot_banker)
    local max_id = 0
    local max_rtm = 0
    if not is_robot_banker then
        max_rtm = 100000000000
    end
    
    --循环每一种情况,求返钱数最大的
    for id,w in pairs(Weight_list) do
        local odds = get_odd_by_result(id)
        local bet_id = id % 1000
        if w > 0 and odds > 0 and total_bet_list[bet_id] then
            local rtm = odds * total_bet_list[bet_id]   --返钱数
            local associations = association_with_num[bet_id]
            for _, v in ipairs(associations) do
                rtm = rtm + get_odd_by_result(v) * (total_bet_list[v] or 0)
            end
            if is_robot_banker then
                if max_rtm < rtm then
                    max_rtm = rtm
                    max_id = id
                end
            else
                if max_rtm > rtm then
                    max_rtm = rtm
                    max_id = id
                end
            end
        end
    end
    
    return max_id
end

--
--检测随机结果的正确性,玩家做庄保证玩家够输
--
function SlotTool.check_random_spin_result(spin_result)
    return true
end

--
--保存奖励记录
--
function SlotTool.save_prize_records(gamename, prize_list)
    local records = {}
    local key = (gamename or "") .. "_prize_records"
    local result,data = redisdao.query_data(".gmmqredis", "get", key)
    if result and data then
        records = json.decode(data) or {}
    end
    
    for _,prize_id in pairs(prize_list or {}) do
        local id = tostring(prize_id)
        records[id] = (tonumber(records[id]) or 0) + 1
    end
    records.total_count = (tonumber(records.total_count) or 0) + 1
    redisdao.query_data(".gmmqredis", "set", key, json.encode(records))

    ---------------------------------

    --辅助函数1
    local function helper_func(val)
        local cnt = 0
        local tmp = val
        while val >= 10 do
            val = math.floor(val / 10)
            cnt = cnt + 1
        end
        if math.floor(10^cnt) == tmp then
            return true
        end
        return false
    end

    --辅助函数2
    local function func(records)
        local porp_list = {}
        local subprop_list = {}
        local cnt = records.total_count or 0
        if cnt == 0 then
            return
        end

        for k,v in pairs(records) do
            if type(v) ~= "table" and k ~= "total_count" then
                v = tonumber(v) or 0
                porp_list[k] = string.format("%g%%",math.floor(v / cnt * 10000) / 100)
            elseif k == "total_count" then
                porp_list[k] = v
            else
                subprop_list[k] = func(v)
            end
        end
        return porp_list,subprop_list
    end

    --开奖次数每增加10倍，统计一次概率
    if helper_func(records.total_count) then
        local porp_list,subprop_list = func(records)
        filelog.sys_obj("prop_list", records.total_count, porp_list, "=================\n", subprop_list)
    end
    ---------------

    return true
end

-------------------------------
----------
--外部接口

local CMD = {}

local cs = queue()

-----------------
----

-- 根据下注区域id获取对应倍率，下注区域范围说明在 Odds_type👆
function CMD.get_odd_by_result(result_id)
    return get_odd_by_result(result_id)
end

-- 根据开出数字获得关联下注区域额
function CMD.get_association_with_num(num)
    if not num or num < 0 or num > 36 then return end
    return association_with_num[num] or {}
end

--
--获取随机旋转结果
--total_bet_list 总下注列表
--total_bet 总下住值
--avg_bet 平均下注值
--is_robot_banker 是否机器人做庄
--is_random 是否随机开奖
--
function CMD.get_random_spin_result(gamename, total_bet_list, total_bet, avg_bet, is_robot_banker, is_random)
    local cnt = 0
    while cnt < 100 do
        local spin_result = SlotTool.gen_random_spin_result(gamename,total_bet_list,total_bet,avg_bet,is_robot_banker,is_random)
        if SlotTool.check_random_spin_result(spin_result) then
            return spin_result
        end
        cnt = cnt + 1
    end

    return false
end

--
--保存奖励记录
--
function CMD.save_prize_records(gamename, prize_list)
  return cs(SlotTool.save_prize_records,gamename,prize_list)
end

--
--处理庄家收益
--
function CMD.handle_banker_profit(gamename, total_bet_num, player_win_num)
    local banker_win = total_bet_num - player_win_num
    return banker_win
end

--
--更新图标权值表
--
function CMD.update_picture_weight_list(new_w_list)
    if type(new_w_list) ~= "table" then
        return false
    end

    for k,v in pairs(new_w_list) do
        if Weight_list[k] and v >= 0 then
            Weight_list[k] = v
        end
    end
    
    --更新化概率表,总权值
    if next(new_w_list) ~= nil then
        Prob_list,Total_weight = SlotTool.update_picture_prob_list()
    end

    return true
end

--
--设置系统输钱上限
--
function CMD.set_system_lose_limit(loselimit_base, loselimit_factor)
    loselimit_base = loselimit_base or 0
    loselimit_factor = loselimit_factor or 0.02
    if loselimit_base < 0 or loselimit_factor < 0 then
        return false
    end
    SystemLoseLimit_Base = loselimit_base
    SystemLoseLimit_Factor = loselimit_factor

    return true
end

--
--处理结算结果
--@total_change 总变化值
--@total_water  总流水值
--@total_bet    玩家总下注
--
function CMD.handle_balance_result(gamename, total_change, total_water, total_bet, comment)
    local tax_rate = SlotTool.get_tax_rate_from_redis(gamename)
    local profit_val = math.floor(total_bet * tax_rate * 100) / 100
    local inventory_val = -total_change

    --更新收益值
    local result1 = SlotTool.update_system_profit(gamename, profit_val, comment)
    if result1 then
        inventory_val = inventory_val - profit_val
    end

    --更新库存值，扣除抽水
    local service_fee_rate = SlotTool.get_service_fee_rate_from_redis(gamename)
    local service_fee_val = math.floor(total_water * service_fee_rate * 100) / 100
    inventory_val = inventory_val - service_fee_val

    return SlotTool.update_system_inventory(gamename, inventory_val, comment)
end

--
--获取抽水率
--
function CMD.get_service_fee_rate(gamename)
    return SlotTool.get_service_fee_rate_from_redis(gamename)
end

-----------
--
--初始化
--
local function init()

    --初始化概率表,总权值
    Prob_list,Total_weight = SlotTool.update_picture_prob_list()

    --filelog.print("init slot tool ok!")
end

-------------------
--
skynet.start(function()
    init()
    skynet.dispatch("lua",function(session, source, cmd, ...)
        local f = CMD[cmd]
        if f then
            skynet.retpack(f(...))
        else
            skynet.retpack()
        end
    end)
end)